package io.wongxd.solution.shatter

import android.app.Application
import android.content.Context
import android.content.Intent
import android.view.View
import androidx.annotation.IdRes
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

/**
 * 程序入口
 */
class ShatterManager(private val lifecycleOwner: LifecycleOwner) : LifecycleEventObserver {

    private val shatters = mutableListOf<Shatter>()

    internal val cache = ShatterCache()

    private val newMsgFlow: MutableSharedFlow<ShatterEvent<*>> by lazy {
        MutableSharedFlow()
    }

    companion object {
        // 管理全局上下文
        lateinit var applicationContext: Context

        /** 初始化框架，接收上下文 **/
        fun init(application: Application) {
            applicationContext = application.applicationContext
        }
    }

    init {
        lifecycleOwner.lifecycle.removeObserver(this)
        // 添加了生命周期的监听
        lifecycleOwner.lifecycle.addObserver(this)

        // 协程接收Flow
        lifecycleOwner.lifecycleScope.launch {
            newMsgFlow.collectLatest { event ->
                shatters.forEach { it.onShatterEvent(event.key, event.data) }
            }
        }
    }

    /** 通过Flow发送事件 **/
    fun sendShatterEvent(key: String, data: Any? = null) {
        lifecycleOwner.lifecycleScope.launch {
            newMsgFlow.emit(ShatterEvent(key, data))
        }
    }

    /** 这里只对Destroy生命周期回调做了处理，自动处理页面对应的Shatter销毁逻辑 **/
    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        shatters.forEach { it.onStateChanged(source, event) }

        when (event) {
            Lifecycle.Event.ON_START -> {
                shatters.forEach { it.onStart() }
            }

            Lifecycle.Event.ON_RESUME -> {
                shatters.forEach { it.onResume() }
            }

            Lifecycle.Event.ON_PAUSE -> {
                shatters.forEach { it.onPause() }
            }

            Lifecycle.Event.ON_STOP -> {
                shatters.forEach { it.onStop() }
            }

            Lifecycle.Event.ON_DESTROY -> {
                shatters.forEach { it.onDestroy() }
                destroy()
                source.lifecycle.removeObserver(this)
            }

            else -> {}
        }
    }

    fun onNewIntent(intent: Intent?) {
        if (lifecycleOwner is FragmentActivity) shatters.forEach { it.onNewIntent(intent) }
    }

    fun onRestart() {
        if (lifecycleOwner is FragmentActivity) shatters.forEach { it.onRestart() }
    }

    fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        shatters.forEach { it.onActivityResult(requestCode, resultCode, data) }
    }

    /** 是否允许返回 **/
    fun enableOnBackPressed(): Boolean {
        return if (lifecycleOwner is FragmentActivity) {
            shatters.find { !it.enableOnBackPressed() } == null
        } else {
            true
        }
    }

    fun onHiddenChanged(isHidden: Boolean) {
        if (lifecycleOwner is Fragment)
            shatters.forEach { it.onHiddenChanged(isHidden) }
    }

    /**
     * 入口1 添加Shatter到指定ID的容器中，
     *
     * @param containViewId 指定添加容器的布局Id
     * @param shatter 待添加的子碎片对象
     * @param isAsync 是否以异步加载的方式加载布局
     * @param index 如果有多个布局添加，指定添加到容器中的索引位置
     *
     */
    fun addShatter(@IdRes containViewId: Int, shatter: Shatter, isAsync: Boolean = false, index: Int = -1) = apply {
        shatter.shatterManager = this
        val view: View? = when (lifecycleOwner) {
            is FragmentActivity -> lifecycleOwner.findViewById(containViewId)
            is Fragment -> lifecycleOwner.requireView().findViewById(containViewId)
            else -> null
        }
        addShatter(view, shatter, isAsync, index)
    }

    /**
     * 入口2 添加Shatter到指定的容器中，
     *
     * @param containView 指定添加容器的ViewGroup对象
     * @param shatter 待添加的子碎片对象
     * @param isAsync 是否以异步加载的方式加载布局
     * @param index 如果有多个布局添加，指定添加到容器中的索引位置
     *
     */
    fun addShatter(containView: View?, shatter: Shatter, isAsync: Boolean = false, index: Int = -1) = apply {
        shatter.shatterManager = this
        shatter.containView = containView
        shatter.attachToLifecycleOwner(lifecycleOwner, isAsync, index)

        shatters.add(shatter)
        cache.putShatter(shatter)
    }

    /**
     *入口3 添加非布局类型的Shatter
     *
     * 不需要设置布局的加载方式和索引
     */
    fun addShatter(shatter: Shatter) = apply {
        shatter.shatterManager = this
        shatter.attachToLifecycleOwner(lifecycleOwner, false, -1)

        shatters.add(shatter)
        cache.putShatter(shatter)
    }

    /**
     * 入口4 预加载Shatter对象和布局
     *
     */
    fun preloadShatter(shatter: Shatter, isAsync: Boolean = false) {
        shatter.shatterManager = this
        shatter.preload(lifecycleOwner, isAsync)
    }

    /** 移除指定的Shatter **/
    fun remove(shatter: Shatter) = apply {
        cache.removeShatter(shatter.getTag())
        shatters.remove(shatter)
    }

    /** 找到指定的Shatter **/
    fun <T : Shatter> findShatter(clazz: Class<T>): T? {
        val tag = clazz.simpleName
        val shatter = shatters.find { it.getTag() == tag } ?: return null
        return shatter as T
    }

    /** 销毁全部的Shatter，清空全部缓存 **/
    private fun destroy() {
        cache.clear()
        shatters.clear()
    }
}